package net.softwarefabrik.bde.core.model.platform.internal;

import java.io.File;

import net.softwarefabrik.bde.core.model.BDEConstants;
import net.softwarefabrik.bde.core.model.BDEException;
import net.softwarefabrik.bde.core.model.maven.ArtifactInfo;
import net.softwarefabrik.bde.core.model.maven.RepositoryManager;
import net.softwarefabrik.bde.core.model.platform.PlatformConfiguration;
import net.softwarefabrik.bde.core.model.platform.PlatformProvider;
import net.softwarefabrik.bde.core.model.platform.PlatformVersionInfo;
import net.softwarefabrik.bde.core.util.FileUtil;

/**
 * Base class for <code>PlatformProvider</code> implementations.
 * 
 * @author Matthias Kuespert
 */
public abstract class AbstractPlatformProvider implements PlatformProvider {

    private RepositoryManager repositoryManager = null;
    
    protected AbstractPlatformProvider(RepositoryManager repositoryManager) {
        this.repositoryManager = repositoryManager;
    }
    
    /**
     * @see net.softwarefabrik.bde.core.model.platform.PlatformProvider#getPlatformId()
     */
    public String getPlatformId() {
        return getPlatformName().toLowerCase();
    }

    /**
     * @return The cache directory.
     */
    protected abstract String getCacheDir();

    /**
     * @return The name of the config file.
     */
    protected abstract String getConfigFile();

    /**
     * Creates the runtime platform configuration file. Must be implemented by
     * concrete <code>PlatformProvider</code>s.
     * 
     * @param config The <code>PlatformConfiguration</code> to use.
     * @throws BDEException if something goes wrong
     */
    protected abstract void createRuntimeConfiguration(PlatformConfiguration config) throws BDEException;

    /**
     * @see net.softwarefabrik.bde.core.model.platform.PlatformProvider#getPlatformJar(net.softwarefabrik.bde.core.model.platform.PlatformConfiguration)
     */
    public File getPlatformJar(PlatformConfiguration config) throws BDEException {
        if (null == config) {
            throw new BDEException("No PlatformConfiguration object specified.");
        }
        PlatformVersionInfo versionInfo = config.getVersionInfo();
        if (null == versionInfo) {
            throw new BDEException("No version configured for platform " + getPlatformName());
        }
        ArtifactInfo platformInfo = new ArtifactInfo(getArtifactId(), getGroupId(),
                                                     versionInfo.getVersion(), "jar");
        File platformJar = this.repositoryManager.get(platformInfo);
        return platformJar;
    }

    /**
     * Prepares the platform directory for a platform. Eventually cleans and
     * downloads the platform jar.
     * 
     * @param config The <code>PlatformConfiguration</code> to use.
     * @param relativePlatformDir The relative path of the platform directory.
     * @param platformUrls The URLs to check when downloading the platform jar
     *        (Note: currently only the first URL is checked)
     * @throws BDEException if something goes wrong
     */
    public void preparePlatform(PlatformConfiguration config) throws BDEException {
        if (null == config) {
            throw new BDEException("No PlatformConfiguration object specified.");
        }
        String workingDirectory = config.getWorkingDirectory();
        if (null == workingDirectory || BDEConstants.EMPTY_STRING.equals(workingDirectory)) {
            throw new BDEException("No working directory specified for platform "
                                   + getPlatformName());
        }
        PlatformVersionInfo versionInfo = config.getVersionInfo();
        if (null == versionInfo) {
            throw new BDEException("No version configured for platform " + getPlatformName());
        }
        //
        File platformDir = new File(workingDirectory
                                    + BDEConstants.STD_FILE_SEPARATOR
                                    + getPlatformId());
        // eventually clean the platform and/or cache directories
        if (platformDir.exists()) {
            if (config.doClearWorkspace()) {
                FileUtil.clearDirectory(platformDir);
            } else { // always clear cache!!
                File cacheDir = new File(workingDirectory
                                         + BDEConstants.STD_FILE_SEPARATOR
                                         + getCacheDir());
                if (cacheDir.exists()) {
                    FileUtil.clearDirectory(cacheDir);
                }
            }
        }
        platformDir.mkdir();
        // retrieve the platform jar
        File platformJar = getPlatformJar(config);
        if (!platformJar.exists()) {
            throw new BDEException("Could not find platform jar: " + platformJar.getAbsolutePath());
        }
        createRuntimeConfiguration(config);
    }
}
